package tracks.controllers.methods.sampleMCTS;

import core.game.Observation;
import core.game.StateObservation;
import ontology.Types;
import tools.Vector2d;
//import tracks.controllers.methods.MCTS.DebugConfig;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;

public class Heuristic {
    public Heuristic() {
        ;
    }
    public static final double HUGE_POS = 1000000000;
    public static final double HUGE_NEG = -999999999;
    public static final double keyDistanceCoefficient = 1;
    public static final double getKeyReward = 1000;
    public static final double portalDistanceCoefficient = 1;
    public static final double nearestGemstoneCoefficient = -1;
    public static final double gameScoreCoefficient = 300;


    public double evaluate(StateObservation stateObs) {
        Vector2d avatarPosition = stateObs.getAvatarPosition();
        ArrayList<Observation>[] npcPositions = stateObs.getNPCPositions();
        ArrayList<Observation>[] immovablePositions = stateObs.getImmovablePositions();
        ArrayList<Observation>[] portalPositions = stateObs.getPortalsPositions();
        double score = 0;
        double keyDistance = 0;
        double won = 0;
        double portalDistance = 0;
        double nearestGemstoneDistance = Double.MAX_VALUE;

        if (stateObs.getGameWinner() == Types.WINNER.PLAYER_WINS) return HUGE_POS;
        else if (stateObs.getGameWinner() == Types.WINNER.PLAYER_LOSES) return HUGE_NEG;

        // scan
        int existsWaterKey = 0;
        int existsWaterPortal = 0;
        int existsKey = 0;
        int existsGemstone = 0;
        Vector2d waterKeyPosition = null;
        for (ArrayList<Observation> objs: immovablePositions) {
            if (objs.size() == 0) continue;
            if (objs.get(0).itype == 4) existsWaterKey = 1;
            if (objs.get(0).itype == 19) existsKey = 1;
            if (objs.get(0).itype == 5 || objs.get(0).itype == 6) existsGemstone = 1;
        }

        // 水迷宫，如果存在钥匙先去找钥匙
        if (existsWaterKey == 1) {
            for (ArrayList<Observation> objs : immovablePositions) {
                if (objs.size() == 0 || objs.get(0).itype != 4) continue;
                waterKeyPosition = objs.get(0).position;
                keyDistance = -Math.abs(waterKeyPosition.x - avatarPosition.x) - Math.abs(waterKeyPosition.y - avatarPosition.y);
                break;
            }
        }

        // 水迷宫，如果有传送门的话准备计算传送门的损失
        int existPortal = 0;
        if (portalPositions != null) {
            for (ArrayList<Observation> objs : portalPositions) {
                if (objs.size() == 0 || objs.get(0).itype != 7) continue;
                existPortal = 1;
                Vector2d portalPosition = objs.get(0).position;
                if (existsWaterKey == 0)
                    portalDistance = -Math.abs(portalPosition.x - avatarPosition.x) - Math.abs(portalPosition.y - avatarPosition.y);
                else
                    portalDistance = -Math.abs(portalPosition.x - waterKeyPosition.x) - Math.abs(portalPosition.y - waterKeyPosition.y);
                break;
            }
        }

        // 挖矿游戏的估值：最近的宝石，或者有钥匙的情况下最近的宝箱，会涉及itype=568 19的物体
            int diggerSwitch = 0;
            ArrayList<Observation>[] sortedImmovable = stateObs.getImmovablePositions(avatarPosition);
            for (ArrayList<Observation> objs : sortedImmovable) {
                if (objs.size() == 0) continue;
                int itype = objs.get(0).itype;
                if (itype != 5 && itype != 6 && itype != 8 && itype != 19) continue;
                if (existsWaterPortal==1 || (itype == 8 && existsKey==1)) continue;
                diggerSwitch = 1;
                Vector2d nearest = objs.get(0).position;
                double nearestDistance = Math.abs(nearest.x - avatarPosition.x) + Math.abs(nearest.y - avatarPosition.y);
                nearestGemstoneDistance = (nearestDistance >= nearestGemstoneDistance) ? nearestGemstoneDistance : nearestDistance;
            }


        double gameScore = stateObs.getGameScore();


        score = won
            + keyDistanceCoefficient*keyDistance
//                + getKeyReward * (1-existKey)
            + portalDistanceCoefficient * portalDistance
            + nearestGemstoneCoefficient * nearestGemstoneDistance * diggerSwitch
            + gameScoreCoefficient * gameScore;
            ;


//            System.out.println("exists Water Key "+existsWaterKey);
//            System.out.println("exists Water portal "+existsWaterPortal);
//            System.out.println("exists Key "+existsKey);
//            System.out.println("Water Key distance "+keyDistance);
//            System.out.println("portal distance "+portalDistance);
//            System.out.println("nearest gemstone distance "+nearestGemstoneDistance);
//            System.out.println("---------------------------");
            ;
        return score;
    }
}
